//
//  ViewController.m
//  test
//
//  Created by 吴棒棒 on 2021/10/27.
//

#import "ViewController.h"
#import "XMPPManager/XMPPManager.h"
#import <WebRTC/WebRTC.h>
#import "JanusConnection.h"
#import "RTCSessionDescription+JSON.h"

static NSString * const kARDMediaStreamId = @"ARDAMS";
static NSString * const kARDAudioTrackId = @"ARDAMSa0";
static NSString * const kARDVideoTrackId = @"ARDAMSv0";

@interface ViewController ()<RTCPeerConnectionDelegate,RTCDataChannelDelegate,RTCAudioSessionDelegate,RTCRtpReceiverDelegate, XMPPManagerDelegate,RTCVideoViewDelegate>
{

}
@property (strong, nonatomic) RTCCameraPreviewView *localView;
@property(nonatomic, strong) RTCPeerConnectionFactory *factory;
@property(nonatomic, strong) RTCCameraVideoCapturer *videoCapturer;
@property(nonatomic, strong) RTCDataChannel* localDataChannel;
@property(nonatomic,strong) NSString *sdpStr;
@property(nonatomic, assign) NSInteger count;
@property(nonatomic,strong) NSTimer *timer;

@end

@implementation ViewController
NSMutableDictionary *peerConnectionDict;
RTCPeerConnection *publisherPeerConnection;
RTCVideoTrack *localTrack;
RTCAudioTrack *localAudioTrack;


int height = 0;

@synthesize factory = _factory;
@synthesize localView = _localView;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.sdpStr =  @"";
    
    RTCAudioSessionConfiguration *webRTCConfig =
    [RTCAudioSessionConfiguration webRTCConfiguration];
    webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
    AVAudioSessionCategoryOptionDefaultToSpeaker;
    
    //        webRTCConfig.ioBufferDuration=1;
    webRTCConfig.sampleRate=kRTCAudioSessionLowComplexitySampleRate;
//       webRTCConfig.ioBufferDuration=0.2;
    //        RDLog(@"ioBufferDuration:%f",kRTCAudioSessionHighPerformanceIOBufferDuration);
    [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig];
    
  
    RTCDefaultVideoEncoderFactory * encoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];

    RTCDefaultVideoDecoderFactory*  decoderFactory = [[RTCDefaultVideoDecoderFactory alloc] init];

    self.factory= [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
                                                  decoderFactory:decoderFactory];

    peerConnectionDict = [NSMutableDictionary dictionary];
//    _factory = [[RTCPeerConnectionFactory alloc] init];

    localAudioTrack = [self createLocalAudioTrack];
    localTrack = [self createLocalVideoTrack];
    
    _localView = [[RTCCameraPreviewView alloc] initWithFrame:CGRectMake(0, 0, 480, 360)];
    [self.view addSubview:_localView];
    _localView.captureSession = self.videoCapturer.captureSession;

    NSString *userName = @"wbb";
    NSString *userPassword = @"wbb123";
    NSString *serverIP = @"172.16.103.12";
    [self loginWith:userName pwd:userPassword serverIP:serverIP];

//    [self addSdpTimer];
    
    [self createPublisherPeerConnection];

}

- (RTCEAGLVideoView *)createRemoteView {

    RTCEAGLVideoView *remoteView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    remoteView.contentMode=UIViewContentModeScaleAspectFill;
    remoteView.delegate = self;
    [self.view addSubview:remoteView];
    return remoteView;
}

- (void)createPublisherPeerConnection {
    publisherPeerConnection = [self createPeerConnection];
//    [publisherPeerConnection addTransceiverWithTrack:localAudioTrack];
//    [publisherPeerConnection addTransceiverWithTrack:localTrack];
    
//    [publisherPeerConnection addTransceiverOfType:RTCRtpMediaTypeAudio];
//    [publisherPeerConnection addTransceiverOfType:RTCRtpMediaTypeVideo];
    
    [self createAudioSender:publisherPeerConnection];
    [self createVideoSender:publisherPeerConnection];
}

- (RTCMediaConstraints *)defaultPeerConnectionConstraints {
    NSDictionary *optionalConstraints = @{ @"DtlsSrtpKeyAgreement" : @"true" };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil  optionalConstraints:optionalConstraints];
    return constraints;
}

- (RTCIceServer *)defaultSTUNServer {
    NSArray *array = [NSArray arrayWithObject:@"stun:47.114.110.197:23478"];
    RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:array
                                                              username:@""
                                                            credential:@"" tlsCertPolicy:RTCTlsCertPolicyInsecureNoCheck];
    return iceServer;
}

- (RTCPeerConnection *)createPeerConnection {
    RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints];
    RTCConfiguration *config = [[RTCConfiguration alloc] init];
    NSMutableArray *iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
    config.iceServers = iceServers;
    config.iceTransportPolicy = RTCIceTransportPolicyAll;
    //config.sdpSemantics = RTCSdpSemanticsUnifiedPlan;
    RTCPeerConnection *peerConnection = [_factory peerConnectionWithConfiguration:config
                                         constraints:constraints
                                            delegate:self];
    return peerConnection;
}

- (void)offerPeerConnection: (NSNumber*) handleId {
    JanusConnection *jc = [[JanusConnection alloc] init];
    jc.connection = publisherPeerConnection;
    jc.handleId = handleId;
    peerConnectionDict[handleId] = jc;

//    [self createDataChannelWithPeerConnection:publisherPeerConnection connectionId:[NSString stringWithFormat:@"%@",handleId]];

    [publisherPeerConnection answerForConstraints:[self defaultOfferConstraints]
                       completionHandler:^(RTCSessionDescription *sdp,
                                           NSError *error) {
        
        NSLog(@"setLocalDescription======%@",sdp);
        
        [publisherPeerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
            
            [self offerSdp:sdp.sdp];
            [self performSelector:@selector(addSdpTimer) withObject:nil afterDelay:2];

        }];
    }];
    
    
}
- (void)addSdpTimer
{
    
  
    NSString *str = publisherPeerConnection.localDescription.sdp;
    NSLog(@"publisherPeerConnection ======== %@", str);
    if (str) {
        [self offerSdp:str];
    }
    
    
}
- (void)createDataChannelWithPeerConnection:(RTCPeerConnection*)peerConnection connectionId:(NSString*)connectionId{
    //给p2p连接创建dataChannel
    RTCDataChannelConfiguration *dataChannelConfiguration = [[RTCDataChannelConfiguration alloc] init];
    dataChannelConfiguration.isNegotiated = NO;
    self.localDataChannel = [peerConnection dataChannelForLabel:@"localDataChannel" configuration:dataChannelConfiguration];
     self.localDataChannel.delegate = self;
//    [self.localDataChannelDictionary setObject:self.localDataChannel forKey:connectionId];//本地记录一下
}
- (RTCMediaConstraints *)creatConstraintWithOption{
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@{kRTCMediaConstraintsOfferToReceiveAudio:kRTCMediaConstraintsValueTrue,kRTCMediaConstraintsOfferToReceiveVideo:kRTCMediaConstraintsValueTrue} optionalConstraints:nil];
    return constraints;
}
- (RTCMediaConstraints *)defaultMediaAudioConstraints {
    
    NSDictionary *mandatoryConstraints = @{@"noiseSuppression": @"true",@"echoCancellation": @"true"};
    RTCMediaConstraints *constraints =
    [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints
                                          optionalConstraints:nil];
    return constraints;
}


- (RTCMediaConstraints *)defaultOfferConstraints {
    NSDictionary *mandatoryConstraints = @{
                                           @"OfferToReceiveAudio" : @"true",
                                           @"OfferToReceiveVideo" : @"true"
                                           };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:nil];
    return constraints;
}

- (RTCAudioTrack *)createLocalAudioTrack {

    RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints];
    RTCAudioSource *source = [_factory audioSourceWithConstraints:constraints];
    RTCAudioTrack *track = [_factory audioTrackWithSource:source trackId:kARDAudioTrackId];

    return track;
}

- (RTCRtpSender *)createAudioSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindAudio streamId:kARDMediaStreamId];
    if (localAudioTrack) {
        sender.track = localAudioTrack;
    }
    return sender;
}


- (RTCVideoTrack *)createLocalVideoTrack
{
    RTCVideoSource *videoSource=self.factory.videoSource;
  //  RTCFileVideoCapturer *videoCapturer=[[RTCFileVideoCapturer alloc] initWithDelegate:videoSource];
    RTCMediaConstraints *cameraConstraints = [[RTCMediaConstraints alloc]
                                              initWithMandatoryConstraints:[self currentMediaConstraint]
                                              optionalConstraints: nil];

    self.videoCapturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:videoSource];
    RTCVideoTrack *videoTrack=[self.factory videoTrackWithSource:videoSource trackId:kARDMediaStreamId];
    return videoTrack;


}
- (RTCRtpSender *)createVideoSender:(RTCPeerConnection *)peerConnection {
    RTCRtpSender *sender = [peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo
                                                 streamId:kARDMediaStreamId];
    if (localTrack) {
        sender.track = localTrack;
    }

    return sender;
}

- (nullable NSDictionary *)currentMediaConstraint {
    NSDictionary *mediaConstraintsDictionary = nil;

    NSString *widthConstraint = @"480";
    NSString *heightConstraint = @"360";
    NSString *frameRateConstrait = @"20";
    if (widthConstraint && heightConstraint) {
        mediaConstraintsDictionary = @{
//                                       kRTCMediaConstraintsValueTrue : widthConstraint,
//                                       kRTCMediaConstraintsMaxWidth : widthConstraint,
//                                       kRTCMediaConstraintsMinHeight : heightConstraint,
//                                       kRTCMediaConstraintsMaxHeight : heightConstraint,
//                                       kRTCMediaConstraintsMaxFrameRate: frameRateConstrait,
                                       };
    }
    return mediaConstraintsDictionary;
}

- (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size {
    CGRect rect = videoView.frame;
    rect.size = size;
    NSLog(@"========didChangeVideiSize %fx%f", size.width, size.height);
    videoView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width/size.width*size.height);
}


- (void)peerConnection:(RTCPeerConnection *)peerConnection didAddStream:(RTCMediaStream *)stream {
    NSLog(@"=========didAddStream");
//    JanusConnection *janusConnection;
//
//    for (NSNumber *key in peerConnectionDict) {
//        JanusConnection *jc = peerConnectionDict[key];
//        if (peerConnection == jc.connection) {
//            janusConnection = jc;
//            break;
//        }
//    }

    dispatch_async(dispatch_get_main_queue(), ^{
        if (stream.videoTracks.count) {
            RTCVideoTrack *remoteVideoTrack = stream.videoTracks[0];

            RTCEAGLVideoView *remoteView = [self createRemoteView];
            [remoteVideoTrack addRenderer:remoteView];
            localTrack = remoteVideoTrack;
  
        }
    });
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveStream:(RTCMediaStream *)stream {
    NSLog(@"=========didRemoveStream");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel {

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)stateChanged {
    NSLog(@"stateChanged === %ld", (long)stateChanged);
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate {

    NSNumber *handleId;
    for (NSNumber *key in peerConnectionDict) {
        JanusConnection *jc = peerConnectionDict[key];
        if (peerConnection == jc.connection) {
            handleId = jc.handleId;
            break;
        }
    }
    
    
    

//    if (candidate.sdp == nil) {
//        NSString *sdpStr = peerConnection.localDescription.sdp;
//        NSLog(@"sdpStr    ====== %@", sdpStr);
//
////        [self offerSdp:candidate.sdp];
//
//    } else {
//        NSLog(@"candidate    ====== %@", candidate);
//
//
//    }
    
    self.count = 0;
    
    
//    if (candidate == nil) {
//        NSString *sdpStr = peerConnection.localDescription.sdp;
//        NSLog(@"sdpStr    ====== %@", sdpStr);
//
//    }else {
//        NSLog(@"candidate    ====== %@", candidate);
//
//    }
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState
{
    NSLog(@"RTCIceGatheringState === %ld", (long)newState);
}

- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection {

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState {
    NSLog(@"RTCIceGatheringState === %ld", (long)newState);
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveIceCandidates:(NSArray<RTCIceCandidate *> *)candidates {
    NSLog(@"=========didRemoveIceCandidates");
}


// mark: delegate

- (void)onPublisherJoined: (NSNumber*) handleId {
    [self offerPeerConnection:handleId];
}

- (void)onPublisherRemoteJsep:(NSNumber *)handleId dict:(NSDictionary *)jsep {
    JanusConnection *jc = peerConnectionDict[handleId];
    
    RTCSessionDescription *answerDescription = [RTCSessionDescription descriptionFromJSONDictionary:jsep];
    [publisherPeerConnection setRemoteDescription:answerDescription completionHandler:^(NSError * _Nullable error) {
        if (error!=nil) {
            NSLog(@"error:%@,%@",error.localizedDescription,error.localizedFailureReason);
        }
        [self offerPeerConnection:@0];

    }];
}

- (void)subscriberHandleRemoteJsep: (NSNumber *)handleId dict:(NSDictionary *)jsep {
    RTCPeerConnection *peerConnection = [self createPeerConnection];

    JanusConnection *jc = [[JanusConnection alloc] init];
    jc.connection = peerConnection;
    jc.handleId = handleId;
    peerConnectionDict[handleId] = jc;

    RTCSessionDescription *answerDescription = [RTCSessionDescription descriptionFromJSONDictionary:jsep];
    [peerConnection setRemoteDescription:answerDescription completionHandler:^(NSError * _Nullable error) {
    }];
    NSDictionary *mandatoryConstraints = @{
                                           @"OfferToReceiveAudio" : @"true",
                                           @"OfferToReceiveVideo" : @"true",
                                           };
    RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:nil];

    [peerConnection answerForConstraints:constraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
        [peerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
        }];
//        [websocket subscriberCreateAnswer:handleId sdp:sdp];
    }];

}

- (void)onLeaving:(NSNumber *)handleId {
    JanusConnection *jc = peerConnectionDict[handleId];
    [jc.connection close];
    jc.connection = nil;
    RTCVideoTrack *videoTrack = jc.videoTrack;
    [videoTrack removeRenderer: jc.videoView];
    videoTrack = nil;
    [jc.videoView renderFrame:nil];
    [jc.videoView removeFromSuperview];

    [peerConnectionDict removeObjectForKey:handleId];
}




//登录页面代理回调用户名和密码
- (void)loginWith:(NSString *)userName pwd:(NSString *)pwd serverIP:(NSString *)ip
{
    //初始化服务器连接管理

    [XMPPManager manager].theHostIP=ip;
    [XMPPManager manager].delegate = self;
    [[XMPPManager manager] setUserName:userName password:pwd];
    BOOL coonect = [[XMPPManager manager] connectServer];
    if (coonect) {
        NSLog(@"连接成功");

    }
    else
    {
        NSLog(@"连接失败");
    }
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self sendMessage];
}
#pragma mark XMPPManager 代理；

//收到消息
- (void)didReceiveMessage:(XMPPMessage *)message
{

    if(message==nil)
    {
        return;
    }
    NSString *body = [[message elementForName:@"body"] stringValue];
    NSString *displayName = [[message from] user];
    NSData *data = [body dataUsingEncoding:NSUTF8StringEncoding];
    if(data!=nil)
    {
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"didReceiveMessage:%@",dic);
        if([dic[@"id"] intValue] == 0) {
            NSDictionary *result_dic = dic[@"result"];
            if ([result_dic[@"message"] isEqualToString:@"success"]) {
                NSDictionary * sdp_dic=[result_dic objectForKey:@"sdp"];

                [self onPublisherRemoteJsep:@0 dict:sdp_dic];
                

                if ([sdp_dic[@"type"] isEqualToString:@"offer"]) {
                    NSString *sdp_str = sdp_dic[@"sdp"];
        

                }
            }
        }

    }

}
//用户登录
- (void)userLoginSuccess:(XMPPJID *)userJID
{
    NSLog(@"用户：%@ 登录成功",userJID.user);
    XMPPPresence *presence = [XMPPPresence presence];
    NSString *toStr = @"dev_6_18@guiji.ai";
    [presence addAttributeWithName:@"type" stringValue:@"available"];
    [presence addAttributeWithName:@"to" stringValue:toStr];
    [[XMPPManager manager].xmppStream sendElement:presence];
//    [self offerPeerConnection:@0];
}

//新用户在线
- (void)newUserOnline:(XMPPPresence *)presence
{
    NSString *user = [[presence from] user];
    NSLog(@"发现用户：%@ 上线",user);

}

//用户下线
- (void)hasUserOffline:(XMPPPresence *)presence
{
    NSString *user = [[presence from] user];
    NSLog(@"发现用户：%@ 离线",user);
    [self onLeaving:0];
}

- (void)sendMessage
{
    NSDictionary* bodydic = @{
        
        @"method":@"MakeNewSession",
        
        @"params":@{
            
            @"sessionId":@"2bd3fa34-21da-4762-8fdc-7e92e4cec8b4",
            
            @"dumpSession":@1,
            
            @"data":@{
                
                @"bg_img":@"https://robot.guiji.ai/nfs/duix-cc/background/MetaHumanSample.png",
                
                @"sequence":@[
                    
                    @"https://kun.guiji.ai/model/2021/10/14/25dea00922e94b7b83996447abb6fb86.mp4"
                    
                ],
                
                @"udCode":@"213354538352709"
                
            }
            
        },
        
        @"id":@0
        
    };
    
    NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodydic options:NSJSONWritingPrettyPrinted error:nil];
    if (bodyData!=nil)
    {
        NSString *body_str = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
        NSString *toStr = @"dev_6_18@guiji.ai";
        
        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:body_str];
        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:toStr];
        [message addChild:body];
        
        
        
        NSLog(@"发送消息给XMPP:%@",message);
        
        [[XMPPManager manager].xmppStream sendElement:message];
    }
    
    
}
- (void)offerSdp:(NSString *)sdp {
    
    
//    sdp = [sdp stringByReplacingOccurrencesOfString:@"a=group:BUNDLE audio video" withString:@"a=group:BUNDLE 0 1"];
//    sdp = [sdp stringByReplacingOccurrencesOfString:@"m=audio " withString:@"m=0 "];//a=mid:audio
//    sdp = [sdp stringByReplacingOccurrencesOfString:@"a=mid:audio" withString:@"a=mid:0"];
//    sdp = [sdp stringByReplacingOccurrencesOfString:@"m=video " withString:@"m=1 "];//a=mid:audio
//    sdp = [sdp stringByReplacingOccurrencesOfString:@"a=mid:video" withString:@"a=mid:1"];
    NSDictionary *bodydic = @{
        @"method":@"AnswerSession",
        @"params":@{
            @"sdp":@{
                @"type":@"answer",
                @"sdp":sdp
            },
            @"sessionId":@"2bd3fa34-21da-4762-8fdc-7e92e4cec8b4"
        },
        @"id":@1
    };
    
    NSData *bodyData = [NSJSONSerialization dataWithJSONObject:bodydic options:NSJSONWritingPrettyPrinted error:nil];
    if (bodyData!=nil)
    {
        NSString *body_str = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
        
        NSLog(@"bodydic ===== %@", body_str);

        NSString *toStr = @"dev_6_18@guiji.ai";
        
        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:body_str];
        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:toStr];
        [message addChild:body];
        
        
        
        NSLog(@"发送消息给XMPP:%@",message);
        
        [[XMPPManager manager].xmppStream sendElement:message];
    }
}
@end
